﻿#include "GUIAbsPostCurvePlotWidget.h"
#include "ui_GUIAbsPostCurvePlotWidget.h"
#include "GUICurvePlotSettingsDialog.h"

#include "FITK_Component/FITKPlotWindow/FITKXYPlotCurveStyle.h"
#include "FITK_Component/FITKPlotWindow/FITKPlotWindowsInterface.h"
#include "FITK_Component/FITKPlotWindow/FITKXYPlotWindow.h"
#include "FITK_Component/FITKPlotWindow/FITKXYPlotProperty.h"
#include "FITK_Component/FITKPlotWindow/FITKXYCurveDrawManager.h"

#include "FITK_Kernel/FITKCore/FITKOperatorRepo.h"
#include "FITK_Kernel/FITKAppFramework/FITKAppFramework.h"
#include "FITK_Kernel/FITKAppFramework/FITKGlobalData.h"
#include "FITK_Kernel/FITKAppFramework/FITKComponents.h"
#include <QTableWidget>
#include <QTableView>
#include <QCheckBox>
#include <QHeaderView>
#include <QToolBar>
#include <QtCore/qmath.h>

namespace GUI
{
    GUIAbsPostCurvePlotWidget::GUIAbsPostCurvePlotWidget(Core::FITKActionOperator* oper, QWidget *parent, bool isAotoDelete) :
        GUIWidgetBase(parent),
        _oper(oper),
        _ui(new Ui::GUIAbsPostCurvePlotWidget)
    {
        _ui->setupUi(this);
        //去掉问号
        Qt::WindowFlags flags = windowFlags();
        flags &= ~Qt::WindowContextHelpButtonHint;
        setWindowFlags(flags);
        //初始化窗口
        this->initWindow();
    }

    GUIAbsPostCurvePlotWidget::~GUIAbsPostCurvePlotWidget()
    {
        if (_ui) {
            delete _ui;
            _ui = nullptr;
        }
        if (_curvePlotSettingWidget) delete _curvePlotSettingWidget;
    }

    Plot::FITKXYPlotProperty* GUIAbsPostCurvePlotWidget::getCurvePlotProp()
    {
        if (!_xyPlotWindow) return nullptr;
        return _xyPlotWindow->getPlotProperty();
    }

    void GUIAbsPostCurvePlotWidget::curvePlotOptionSlot()
    {
        if (!_curvePlotSettingWidget) return;
        int flag = _curvePlotSettingWidget->exec();
        if (flag != QDialog::Accepted) return;
        //更新曲线图的属性
        _curvePlotSettingWidget->updateCurvePlot(_xyPlotWindow);
        //获取设置的频率范围和算法参数
        double freqRange[2]{ 0.0, 0.0 }, dBValue = 0.0;
        bool isAWeight = false;
        _curvePlotSettingWidget->getFreqRange(freqRange);
        _curvePlotSettingWidget->getYAxisCalcValue(isAWeight, dBValue);
        this->updateTableAndCurvePlot(freqRange, isAWeight, dBValue);
    }

    void GUIAbsPostCurvePlotWidget::initWindow()
    {
        //创建表格和后处理曲线图
        Plot::FITKPlotWindowsInterface* plotWindows = FITKAPP->getComponents()->getComponentTByName<Plot::FITKPlotWindowsInterface>("FITKPlotWindowsInterface");
        if (!plotWindows) return;
        _xyPlotWindow = dynamic_cast<Plot::FITKXYPlotWindow*>(plotWindows->getWidget(0));
        _tableWidget = new QTableWidget();
        _curvePlotSettingWidget = new GUICurvePlotSettingsDialog(this);
        //初始化窗口
        _ui->splitter_h1->addWidget(_tableWidget);
        _ui->splitter_h1->addWidget(_xyPlotWindow);
        //初始化曲线选项
        QToolBar* toolBar = _xyPlotWindow->getToolBar();
        if (!toolBar) return;
        QAction* action = toolBar->addAction(QIcon(":FITKIcons/icoR_options.svg"), "Option");
        connect(action, SIGNAL(triggered()), this, SLOT(curvePlotOptionSlot()));
        //初始化曲线的设置
        Plot::FITKXYPlotProperty* propCurvePlot = _xyPlotWindow->getPlotProperty();
        if (!propCurvePlot) return;
        propCurvePlot->setPlotMagnifier(false);
        propCurvePlot->setPlotPanner(false);
    }


    void GUIAbsPostCurvePlotWidget::initTableAndCurvePlot(std::vector<float>* freqValue, QHash<QString, std::vector<float>>* paraValue)
    {
        if (!freqValue || !paraValue) return;
        //设置数据
        _freqValue = *freqValue;
        _paraValue = *paraValue;
        //更新表格和曲线数据
        this->updateTableAndCurvePlot();
        //初始化曲线选项
        _curvePlotSettingWidget->init(freqValue, _xyPlotWindow);
    }

    void GUIAbsPostCurvePlotWidget::setDBDefault(double v)
    {
        _dBDefault = v;
    }

    QString GUIAbsPostCurvePlotWidget::doubleToString(double value)
    {
        return QString::number(value, 'g', 6);
    }

    void GUIAbsPostCurvePlotWidget::updateTableAndCurvePlot(double* freqRange, bool isAWeight, double dBValue)
    {
        if (!_tableWidget || !_xyPlotWindow || _freqValue.size() == 0) return;
        //清理数据
        Plot::FITKXYCurveDrawManager* curveDrawManager = _xyPlotWindow->getCurveManager();
        if (!curveDrawManager) return;
        _tableWidget->clear();
        curveDrawManager->clear();
        //获取数量
        int freqCount = _freqValue.size();
        //获取频率范围
        double startFreq = _freqValue[0], endFreq = _freqValue[freqCount - 1];
        if (freqRange)
        {
            startFreq = freqRange[0];
            endFreq = freqRange[1];
        }
        //初始化表格-频谱
        _tableWidget->setColumnCount(1);
        _tableWidget->setRowCount(1);
        _tableWidget->setItem(0, 0, new QTableWidgetItem("Overall"));
        QVector<double> xData;
        for (std::vector<float>::iterator iterFreq = _freqValue.begin(); iterFreq != _freqValue.end(); ++iterFreq)
        {
            if (*iterFreq < startFreq || *iterFreq > endFreq) continue;
            //设置行数
            int row = _tableWidget->rowCount();
            _tableWidget->setRowCount(row + 1);
            //保存数据和设置表格数据
            xData.push_back(*iterFreq);
            _tableWidget->setItem(row, 0, new QTableWidgetItem(doubleToString(*iterFreq)));
        }
        //初始化表格-参数数据
        QStringList header;
        header << "Hz";
        for (QHash<QString, std::vector<float>>::iterator iter = _paraValue.begin(); iter != _paraValue.end(); ++iter)
        {
            if (iter.value().size() != freqCount) continue;
            //设置列数
            int column = _tableWidget->columnCount();
            _tableWidget->setColumnCount(column + 1);
            //获取表头数据
            header << iter.key();
            //保存数据和设置表格数据
            QVector<double> yData;
            double overAll = 0.0;
            int index = 0;
            int i = 0;
            for (std::vector<float>::iterator iterFreq = _freqValue.begin(); iterFreq != _freqValue.end(); ++iterFreq, ++index)
            {
                if (*iterFreq < startFreq || *iterFreq > endFreq) continue;
                ++i;
                double value = calcParaData(iter.value()[index], *iterFreq, isAWeight, dBValue);
                yData.push_back(value);
                _tableWidget->setItem(i, column, new QTableWidgetItem(doubleToString(value)));
                overAll += calcOverAll(value, isAWeight, dBValue, false);
            }
            overAll = calcOverAll(overAll, isAWeight, dBValue, true);
            _tableWidget->setItem(0, column, new QTableWidgetItem(doubleToString(overAll)));
            //创建曲线
            Plot::FITKXYCurveDrawProp* curveData = new Plot::FITKXYCurveDrawProp;
            curveData->setData(iter.key(), xData, yData);
            curveDrawManager->appendGraphObj(curveData);
        }
        //设置表头
        _tableWidget->setHorizontalHeaderLabels(header);
        _tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
        _tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
        //更新曲线图
        _xyPlotWindow->updataCanvas(true);
    }

    double GUIAbsPostCurvePlotWidget::calcParaData(double value, double freqValue, bool isAWei, double dbUserValue)
    {
        double result = value;
        if (dbUserValue > 0.0)
        {
            result = _dBDefault * log10(value / dbUserValue);
        }
        if (isAWei)
        {
            double hz = this->getAWeightingValue(freqValue);
            result = result + hz;
        }
        return result;
    }

    double GUIAbsPostCurvePlotWidget::calcOverAll(double value, bool isAWei, double dbUserValue, bool isAll)
    {
        double result = value;
        if (dbUserValue > 0.0)
        {
            if (isAll)
                result = 10 * log10(value);
            else
                result = qPow(10, (0.1 * value));
        }
        return result;
    }

    double GUIAbsPostCurvePlotWidget::getAWeightingValue(double freq)
    {
        double value = 0.0;
        if (freq - 10.0 < 1e-16) value = -70.4;
        else if (freq - 12.5 < 1e-16) value = -63.4;
        else if (freq - 16 < 1e-16) value = -56.7;
        else if (freq - 20 < 1e-16) value = -50.5;
        else if (freq - 25 < 1e-16) value = -44.7;
        else if (freq - 31.5 < 1e-16) value = -39.4;
        else if (freq - 40 < 1e-16) value = -34.6;
        else if (freq - 50 < 1e-16) value = -30.2;
        else if (freq - 63 < 1e-16) value = -26.2;
        else if (freq - 80 < 1e-16) value = -22.5;
        else if (freq - 100 < 1e-16) value = -19.1;
        else if (freq - 125 < 1e-16) value = -16.1;
        else if (freq - 160 < 1e-16) value = -13.4;
        else if (freq - 200 < 1e-16) value = -10.9;
        else if (freq - 250 < 1e-16) value = -8.6;
        else if (freq - 315 < 1e-16) value = -6.6;
        else if (freq - 400 < 1e-16) value = -4.8;
        else if (freq - 500 < 1e-16) value = -3.2;
        else if (freq - 630 < 1e-16) value = -1.9;
        else if (freq - 800 < 1e-16) value = -0.8;
        else if (freq - 1000 < 1e-16) value = 0.0;
        else if (freq - 1250 < 1e-16) value = 0.6;
        else if (freq - 1600 < 1e-16) value = 1.0;
        else if (freq - 2000 < 1e-16) value = 1.2;
        else if (freq - 2500 < 1e-16) value = 1.3;
        else if (freq - 3150 < 1e-16) value = 1.2;
        else if (freq - 4000 < 1e-16) value = 1;
        else if (freq - 5000 < 1e-16) value = 0.5;
        else if (freq - 6300 < 1e-16) value = -0.1;
        else if (freq - 8000 < 1e-16) value = -1.1;
        else if (freq - 10000 < 1e-16) value = -2.5;
        else if (freq - 12500 < 1e-16) value = -4.3;
        else if (freq - 16000 < 1e-16) value = -6.6;
        else if (freq - 20000 < 1e-16) value = -9.3;
        else value = -9.3;
        return value;
    }
}
